﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using TigerAndGoats.Control;
using TigerAndGoats.Framework;
using TigerAndGoats.Resources;

namespace TigerAndGoats.Sprites
{
    public class Tiger: Piece
    {
        public Tiger()
        {
            this._image = new System.Drawing.Bitmap(@"Resources\tiger.png");
            this._image_Gray = new System.Drawing.Bitmap(@"Resources\tiger_Gray.png");
        }

        private List<Tuple<GraphNode, DestinationTip>> _actualReachablePaths = new List<Tuple<GraphNode, DestinationTip>>();

        public override void Draw(Graphics graphics)
        {
            if (_location != null)
            {
                if (GameControl.currentRound == GameControl.Round.Tiger)
                {
                    DrawMyImage(graphics, _image);
                }
                else
                {
                    DrawMyImage(graphics, _image_Gray);
                }
            }
        }

        private void DrawMyImage(Graphics graphics, Bitmap myImage)
        {
            graphics.DrawImage(myImage, new Rectangle(
                                GetPieceLocation(GetPointByOrdinate(_location.GetOrdinate())
                                , GlobalSettings.PieceSizeTiger(GetPutupRatio()))
                                , GlobalSettings.PieceSizeTiger(GetPutupRatio())
                                )
                            );
        }

        public override void PutUp(Action action = null)
        {
            if (Piece.currentPutUp == Piece.Empty 
                && GameControl.CurrentGameState == GameControl.GameState.InProcess
                && GameControl.currentRound == GameControl.Round.Tiger)
            {
                // 如果 可走路径可能没有被提前检测，则主动检测
                if (_actualReachablePaths.Count <= 0)
                {
                    SetCurrentActualReachablePaths();
                }

                if (_actualReachablePaths.Count > 0)
                {
                    base.PutUp(new Action(() =>
                    {
                        foreach (var pathPairTuple in _actualReachablePaths)
                        {
                            pathPairTuple.Item1.SetPiece(pathPairTuple.Item2);
                        }
                    }));
                }
            }
        }

        public override void PutDown()
        {
            base.PutDown();
            // 这个集合，因为从方法里面被拿出来了，所以需要单独清空
            _actualReachablePaths.Clear();
        }

        public int? SetCurrentActualReachablePaths()
        {// 在设置“_actualReachablePaths”
            // Show next step tip
            foreach (var reachableNode in this._location.GetAllReachableNodes())
            {
                var reachablePieceOnNode = reachableNode.GetPiece();
                if (!(reachablePieceOnNode is Goat) && !(reachablePieceOnNode is Tiger))
                {
                    var reachableDestination = new DestinationTipTiger() { FromPiece = this };
                    _reachableDestinations.Add(reachableDestination);
                    _actualReachablePaths.Add(new Tuple<GraphNode, DestinationTip>(reachableNode, reachableDestination));
                }

                // 判断是否可以吃羊，从而额外确定多余的目标位置
                if (reachablePieceOnNode is Goat)
                {
                    // 先确定这个羊对于老虎的方位
                    var directionName = this.GetGoatDirection(reachablePieceOnNode);
                    var theExtraDestination = SetViaGoats(reachablePieceOnNode, directionName, _actualReachablePaths);
                    if (theExtraDestination != DestinationTipTiger.Empty)
                    {
                        _reachableDestinations.Add(theExtraDestination);
                    }
                }
            }

            if (_actualReachablePaths.Count <= 0)
            {
                GameControl.WinGame(UITipText.GOAT_WIN);
            }

            return _actualReachablePaths?.Count;
        }

        private DestinationTipTiger SetViaGoats(Piece reachablePieceOnNode, string directionName, List<Tuple<GraphNode, DestinationTip>> actualReachablePaths)
        {
            List<Piece> viaGoats = new List<Piece>() { reachablePieceOnNode };

            // 到达越过第一个羊的位置
            var nextNodeOnTheDirection = (GraphNode)this._location.GetType().GetProperty(directionName)
                .GetValue(reachablePieceOnNode.GetLocation());
            // 位置不存在就返回
            if (nextNodeOnTheDirection == GraphNode.Empty)
            {
                return DestinationTipTiger.Empty;
            }

            var thePieceOnNext = nextNodeOnTheDirection.GetPiece();
            // 这个位置为空，正好可以落子，吃掉一个羊
            if (thePieceOnNext == Piece.Empty)
            {
                var reachableDestination = new DestinationTipTiger() { FromPiece = this };
                reachableDestination.AddViaGoats(viaGoats);
                actualReachablePaths.Add(new Tuple<GraphNode, DestinationTip>(nextNodeOnTheDirection, reachableDestination));
                return reachableDestination;
            }

            viaGoats.Add(thePieceOnNext);
            // 到达越过第二个羊的位置
            var nextNodeOnTheDirection2 = (GraphNode)nextNodeOnTheDirection.GetType().GetProperty(directionName)
                .GetValue(thePieceOnNext.GetLocation());
            var thePieceOnNext2 = nextNodeOnTheDirection2.GetPiece();
            // 1. 位置不存在就返回 2.如果空位在越过第二个羊的位置，也需要返回（这个时候老虎不能吃羊）
            if (nextNodeOnTheDirection2 == GraphNode.Empty || thePieceOnNext2 == Empty)
            {
                return DestinationTipTiger.Empty;
            }

            viaGoats.Add(thePieceOnNext2);
            // 到达越过第三个羊的位置
            var nextNodeOnTheDirection3 = (GraphNode)nextNodeOnTheDirection2.GetType().GetProperty(directionName)
                .GetValue(thePieceOnNext2.GetLocation());
            var thePieceOnNext3 = nextNodeOnTheDirection3.GetPiece();

            // 1. 位置不存在就返回
            if (nextNodeOnTheDirection2 == GraphNode.Empty)
            {
                return DestinationTipTiger.Empty;
            }

            // 这个位置为空，正好可以落子，吃掉三个羊
            if (thePieceOnNext3 == Piece.Empty)
            {
                var reachableDestination = new DestinationTipTiger() { FromPiece = this };
                reachableDestination.AddViaGoats(viaGoats);
                actualReachablePaths.Add(new Tuple<GraphNode, DestinationTip>(nextNodeOnTheDirection3, reachableDestination));
                return reachableDestination;
            }

            viaGoats.Add(thePieceOnNext3);
            // 到达越过第四个羊的位置
            var nextNodeOnTheDirection4 = (GraphNode)nextNodeOnTheDirection3.GetType().GetProperty(directionName)
                .GetValue(thePieceOnNext3.GetLocation());

            var thePieceOnNext4 = nextNodeOnTheDirection4.GetPiece();
            // 1. 位置不存在就返回 2.如果空位在越过第四个羊的位置，也需要返回（这个时候老虎不能吃羊）
            if (nextNodeOnTheDirection4 == GraphNode.Empty || thePieceOnNext4 == Empty)
            {
                return DestinationTipTiger.Empty;
            }

            viaGoats.Add(thePieceOnNext4);
            // 到达越过第五个羊的位置
            var nextNodeOnTheDirection5 = (GraphNode)nextNodeOnTheDirection4.GetType().GetProperty(directionName)
                .GetValue(thePieceOnNext4.GetLocation());
            var thePieceOnNext5 = nextNodeOnTheDirection5.GetPiece();

            // 1. 位置不存在就返回
            if (nextNodeOnTheDirection5 == GraphNode.Empty)
            {
                return DestinationTipTiger.Empty;
            }

            // 这个位置为空，正好可以落子，吃掉五个羊
            if (thePieceOnNext5 == Piece.Empty)
            {
                var reachableDestination = new DestinationTipTiger() { FromPiece = this };
                reachableDestination.AddViaGoats(viaGoats);
                actualReachablePaths.Add(new Tuple<GraphNode, DestinationTip>(nextNodeOnTheDirection5, reachableDestination));
                return reachableDestination;
            }

            return DestinationTipTiger.Empty;
        }

        private string GetGoatDirection(Piece reachablePieceOnNode)
        {
            if (this._location.LeftTop.GetPiece() == reachablePieceOnNode)
            {
                return "LeftTop";
            }
            if (this._location.Top.GetPiece() == reachablePieceOnNode)
            {
                return "Top";
            }
            if (this._location.RightTop.GetPiece() == reachablePieceOnNode)
            {
                return "RightTop";
            }
            if (this._location.MiddleLeft.GetPiece() == reachablePieceOnNode)
            {
                return "MiddleLeft";
            }
            if (this._location.MiddleRight.GetPiece() == reachablePieceOnNode)
            {
                return "MiddleRight";
            }
            if (this._location.BottomLeft.GetPiece() == reachablePieceOnNode)
            {
                return "BottomLeft";
            }
            if (this._location.Bottom.GetPiece() == reachablePieceOnNode)
            {
                return "Bottom";
            }
            if (this._location.BottomRight.GetPiece() == reachablePieceOnNode)
            {
                return "BottomRight";
            }

            return string.Empty;
        }
    }
}
